#include "BlockVertexBufferSorter.h"
#include <assert.h>

#define UV_MAC(x, pos) (0.0625f * (pos) + FLT_EPSILON + (((0.0625f * ((pos) + 1) - FLT_EPSILON) - (0.0625f * (pos) + FLT_EPSILON)) * (x)))

float UV_LERP_PIXEL(float t, float min, float max)
{
	min = min * (1.f / 256.f) + FLT_EPSILON;
	max = max * (1.f / 256.f) - FLT_EPSILON;

	return min + (max - min) * t;
}

ID3DXEffect* BlockVertexBufferSorter::m_pEffect = NULL;
IDirect3DIndexBuffer9* BlockVertexBufferSorter::m_pIndexBuffer = NULL;
IDirect3DVertexDeclaration9* BlockVertexBufferSorter::m_pVertDecl = NULL;
IDirect3DTexture9* BlockVertexBufferSorter::m_pBoxTexture = NULL;
IDirect3DVertexBuffer9* BlockVertexBufferSorter::vertBuffers[MAX_TYPE];
int BlockVertexBufferSorter::prims[MAX_TYPE];
int BlockVertexBufferSorter::verts[MAX_TYPE];
D3DXHANDLE BlockVertexBufferSorter::m_hTexture;
D3DXHANDLE BlockVertexBufferSorter::m_hPositions;
D3DXHANDLE BlockVertexBufferSorter::m_hLighting;

void BlockVertexBufferSorter::Init()
{
	static bool Setup = false;
	if (Setup)
		return;

	Setup = true;

	// 24 verts
	BOX_VERTEX_INSTANCE box[] = {
		// Top
		{ D3DXVECTOR3(0.f, 1.f, 1.f), 0.f, 0.f, 0 },
		{ D3DXVECTOR3(1.f, 1.f, 1.f), 1.f, 0.f, 0 },
		{ D3DXVECTOR3(0.f, 1.f, 0.f), 0.f, 1.f, 0 },
		{ D3DXVECTOR3(1.f, 1.f, 0.f), 1.f, 1.f, 0 },
		// Left
		{ D3DXVECTOR3(0.f, 1.f, 1.f), 0.f, 0.f, 0 },
		{ D3DXVECTOR3(0.f, 1.f, 0.f), 1.f, 0.f, 0 },
		{ D3DXVECTOR3(0.f, 0.f, 1.f), 0.f, 1.f, 0 },
		{ D3DXVECTOR3(0.f, 0.f, 0.f), 1.f, 1.f, 0 },
		// Front
		{ D3DXVECTOR3(0.f, 1.f, 0.f), 0.f, 0.f, 0 },
		{ D3DXVECTOR3(1.f, 1.f, 0.f), 1.f, 0.f, 0 },
		{ D3DXVECTOR3(0.f, 0.f, 0.f), 0.f, 1.f, 0 },
		{ D3DXVECTOR3(1.f, 0.f, 0.f), 1.f, 1.f, 0 },
		// Right
		{ D3DXVECTOR3(1.f, 1.f, 0.f), 0.f, 0.f, 0 },
		{ D3DXVECTOR3(1.f, 1.f, 1.f), 1.f, 0.f, 0 },
		{ D3DXVECTOR3(1.f, 0.f, 0.f), 0.f, 1.f, 0 },
		{ D3DXVECTOR3(1.f, 0.f, 1.f), 1.f, 1.f, 0 },
		// Back
		{ D3DXVECTOR3(1.f, 1.f, 1.f), 0.f, 0.f, 0 },
		{ D3DXVECTOR3(0.f, 1.f, 1.f), 1.f, 0.f, 0 },
		{ D3DXVECTOR3(1.f, 0.f, 1.f), 0.f, 1.f, 0 },
		{ D3DXVECTOR3(0.f, 0.f, 1.f), 1.f, 1.f, 0 },
		// Bottom
		{ D3DXVECTOR3(0.f, 0.f, 0.f), 0.f, 0.f, 0 },
		{ D3DXVECTOR3(1.f, 0.f, 0.f), 1.f, 0.f, 0 },
		{ D3DXVECTOR3(0.f, 0.f, 1.f), 0.f, 1.f, 0 },
		{ D3DXVECTOR3(1.f, 0.f, 1.f), 1.f, 1.f, 0 }
	};

	// 36 indicies per box
	DWORD boxIndicies[BUFFER_SIZE * 36];
	for (unsigned int iBox = 0; iBox < BUFFER_SIZE; ++iBox)
	{
		for (unsigned int iFace = 0; iFace < 6; ++iFace)
		{
			unsigned int index = iBox * 36 + iFace * 6;
			unsigned int vert = iBox * 24 + iFace * 4;
			boxIndicies[index + 0] = vert + 0;
			boxIndicies[index + 1] = vert + 1;
			boxIndicies[index + 2] = vert + 2;
			boxIndicies[index + 3] = vert + 2;
			boxIndicies[index + 4] = vert + 1;
			boxIndicies[index + 5] = vert + 3;
		}
	}

	
	// Copy over the indicies (same for every block)
	g_D3D.pDev->CreateIndexBuffer(sizeof(DWORD) * BUFFER_SIZE * 36, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &m_pIndexBuffer, NULL);
	{
		void *data;
		m_pIndexBuffer->Lock(0, NULL, &data, 0);
		memcpy_s(data, sizeof(DWORD) * BUFFER_SIZE * 36, (void *)boxIndicies, sizeof(DWORD) * BUFFER_SIZE * 36);
		m_pIndexBuffer->Unlock();
	}

	D3DVERTEXELEMENT9 VertexElemShader[] =
	{
		{ 0, 0,		D3DDECLTYPE_FLOAT3,	D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_POSITION,	0 },
		{ 0, 12,	D3DDECLTYPE_FLOAT2,	D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_TEXCOORD,	0 },
		{ 0, 20,	D3DDECLTYPE_FLOAT1,	D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_TEXCOORD,	1 },
		D3DDECL_END()
	};

	g_D3D.pDev->CreateVertexDeclaration(VertexElemShader, &m_pVertDecl);
	g_D3D.pDev->SetVertexDeclaration(m_pVertDecl);

	// Load our texture
	D3DXCreateTextureFromFileEx(g_D3D.pDev, "Resources/Textures/terrain.png", D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, 
		D3DFMT_A8B8G8R8, D3DPOOL_DEFAULT, D3DX_FILTER_LINEAR, D3DX_FILTER_NONE, 0, NULL, NULL, &m_pBoxTexture);

	// Get our shader ready
	ID3DXBuffer *errors = NULL;
	D3DXCreateEffectFromFile(g_D3D.pDev, "Resources/Shaders/Instancing.fx", NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &m_pEffect, &errors);
	if (errors)
	{
		char *errorBuff = (char *)errors->GetBufferPointer();
		assert(false && errorBuff);
	}
	m_hTexture = m_pEffect->GetParameterBySemantic(NULL, "TEXTURE");
	m_hPositions = m_pEffect->GetParameterBySemantic(NULL, "BOXINSTANCEARRAY_POSITION");
	m_hLighting = m_pEffect->GetParameterBySemantic(NULL, "BOXINSTANCEARRAY_LIGHT");

	// Make our vectors big
	for (int i = 1; i < MAX_TYPE; ++i)
	{
		blockPosList[i].reserve(1000);
		dataList[i].reserve(1000);
		lightList[i].reserve(1000);
		sizes[i] = 0;

		// Skip cloth
		if (i == GLASS)
			i = 36;
	}

	// Build our data types
	for (int i = 0; i < MAX_TYPE; ++i)
		TypeBuilder((BLOCK_TYPE)i, box);
}

#define __I(x,y,z) ((int)(((x) << 11) + (y) + ((z) << 7)))

float GetLight(int x, int y, int z, const UBYTE *Light, const UBYTE *SkyLight)
{
	int i = __I(x,y,z);
	float light = 0.f;
	if ((i & 1) == 0)
		light = (float)(((Light[i >> 1] >> 4) + (SkyLight[i >> 1] >> 4)) & 0xF) / 15.f;
	else
		light = (float)(((Light[i >> 1] & 0xF) + (SkyLight[i >> 1] >> 4)) & 0xF) / 15.f;

	return light;
}

void BlockVertexBufferSorter::Sort(Chunk const *_chunk)
{
	// Pull out all the block data
	const UBYTE *BlockIDs = _chunk->GetBlockIds();
	const UBYTE *Data = _chunk->GetBlockData();
	const UBYTE *Light = _chunk->GetBlockLight();
	const UBYTE *SkyLight = _chunk->GetBlockSkyLight();

	// Go through all blocks
	for (int i = 0; i < 32768; ++i)
	{
		// Make sure we're not air
		BLOCK_TYPE type = (BLOCK_TYPE)BlockIDs[i];
		if (type == AIR)
			continue;

		// Find our position
		int x, y, z;
		x = i >> 11;
		z = (i - (x << 11)) >> 7;
		y = i - (x << 11) - (z << 7);

		// Check if we'll be visible at all
		// TODO: add support for alpha'd blocks rather than just air
		if ((x != 0 && (BLOCK_TYPE)BlockIDs[__I(x-1,y,z)] != AIR) &&
			(y != 128 && (BLOCK_TYPE)BlockIDs[__I(x,y+1,z)] != AIR) &&
			(z != 0 && (BLOCK_TYPE)BlockIDs[__I(x,y,z-1)] != AIR))
			continue;

		// This block is good, increase the size
		++sizes[type];

		UBYTE data = Data[i >> 1];
		float light;
		if (x == 0 || z == 0 || y == 128)
			light = 1.f;
		else
		{
			light = GetLight(x, y, z, Light, SkyLight);

			float brightLight = 0.f;
			if (x != 0)	brightLight = max(brightLight, GetLight(x - 1, y, z, Light, SkyLight));
			if (x != 16) brightLight = max(brightLight, GetLight(x + 1, y, z, Light, SkyLight));
			if (y != 0) brightLight = max(brightLight, GetLight(x, y - 1, z, Light, SkyLight));
			if (y != 128) brightLight = max(brightLight, GetLight(x, y + 1, z, Light, SkyLight));
			if (z != 0) brightLight = max(brightLight, GetLight(x, y, z - 1, Light, SkyLight));
			if (z != 16) brightLight = max(brightLight, GetLight(x, y, z + 1, Light, SkyLight));

			if (light < brightLight - 1.f / 15.f)
				light = brightLight - 1.f / 15.f;

			if ((i & 1) == 0)
			{
				data = data >> 4;
				const_cast<Chunk *>(_chunk)->GetBlockLight()[i >> 1] = (Light[i >> 1] & 0xF) | ((int)(brightLight * 15.f) << 4);
			}
			else
			{
				data = data & 0xF;
				const_cast<Chunk *>(_chunk)->GetBlockLight()[i >> 1] = (Light[i >> 1] & 0xF0) | ((int)(brightLight * 15.f));
			}

			light = max(light, 0.15f);
		}

		dataList[type].push_back(data);
		blockPosList[type].push_back(D3DXVECTOR4((float)x, (float)y, (float)z, light));
	}
}

#define MIN(x, y) (((x) + (y) - abs((x) - (y))) >> 1)



void BlockVertexBufferSorter::Render(BLOCK_TYPE _type)
{
	if (sizes[_type] == 0)
		return;

	g_D3D.pDev->SetStreamSource(0, vertBuffers[_type], 0, sizeof(BOX_VERTEX_INSTANCE));
	g_D3D.pDev->SetIndices(m_pIndexBuffer);
	m_pEffect->SetTexture(m_hTexture, m_pBoxTexture);

	int nRemainingBlocks = sizes[_type];
	int nRendered = 0;

	unsigned int iPass, cPasses;
	m_pEffect->Begin(&cPasses, 0);
	for (iPass = 0; iPass < cPasses; ++iPass)
	{
		m_pEffect->BeginPass(iPass);
		{
			while (nRemainingBlocks > 0)
			{
				int nToRender = MIN(nRemainingBlocks, BUFFER_SIZE);

				// Pass in our block data
				m_pEffect->SetVectorArray(m_hPositions, &blockPosList[_type][nRendered], nToRender);
				//m_pEffect->SetFloatArray(m_hLighting, &lightList[_type][nRendered], nToRender);
				m_pEffect->CommitChanges();

				g_D3D.pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, nToRender * verts[_type], 0, nToRender * prims[_type]);
				nRemainingBlocks -= nToRender;
				nRendered += nToRender;
			}
		}
		m_pEffect->EndPass();
	}
	m_pEffect->End();

}


void BlockVertexBufferSorter::TypeBuilder(BLOCK_TYPE _type, BOX_VERTEX_INSTANCE *_boxVerts)
{
	BOX_VERTEX_INSTANCE *boxVerts;

	// Modify the uvs based on the block type
	int boxSize = sizeof(BOX_VERTEX_INSTANCE) * 24;
	switch (_type)
	{
	case STONE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 1);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 0);
		}
		break;
	case GRASS:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = 0.f;		boxVerts[0].v = 0.f;
		boxVerts[1].u = 0.0625f;	boxVerts[1].v = 0.f;
		boxVerts[2].u = 0.f;		boxVerts[2].v = 0.0625f;
		boxVerts[3].u = 0.0625f;	boxVerts[3].v = 0.0625f;

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 3);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 0);
		}

		boxVerts[20].u = UV_MAC(0.f, 2); boxVerts[20].v = UV_MAC(0.f, 0);
		boxVerts[21].u = UV_MAC(1.f, 2); boxVerts[21].v = UV_MAC(0.f, 0);
		boxVerts[22].u = UV_MAC(0.f, 2); boxVerts[22].v = UV_MAC(1.f, 0);
		boxVerts[23].u = UV_MAC(1.f, 2); boxVerts[23].v = UV_MAC(1.f, 0);
		break;
	case DIRT:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 2);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 0);
		}
		break;
	case COBBLESTONE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 0);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 1);
		}
		break;
	case WOOD:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 4);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 0);
		}
		break;
	//case SAPLING:

		//break;
	case BEDROCK:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 1);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 1);
		}
		break;
	case WATER:
	case STATIONARY_WATER:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 13);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 12);
		}
		break;
	case LAVA:
	case STATIONARY_LAVA:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 13);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 14);
		}
		break;
	case SAND:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 2);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 1);
		}
		break;
	case GRAVEL:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 3);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 1);
		}
		break;
	case GOLD_ORE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 0);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}
		break;
	case IRON_ORE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 1);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}
		break;
	case COAL_ORE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 2);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}
		break;
	case LOG:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 5); boxVerts[0].v = UV_MAC(0.f, 1);
		boxVerts[1].u = UV_MAC(1.f, 5); boxVerts[1].v = UV_MAC(0.f, 1);
		boxVerts[2].u = UV_MAC(0.f, 5); boxVerts[2].v = UV_MAC(1.f, 1);
		boxVerts[3].u = UV_MAC(1.f, 5); boxVerts[3].v = UV_MAC(1.f, 1);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 4);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 1);
		}

		boxVerts[20].u = UV_MAC(0.f, 5); boxVerts[20].v = UV_MAC(0.f, 1);
		boxVerts[21].u = UV_MAC(1.f, 5); boxVerts[21].v = UV_MAC(0.f, 1);
		boxVerts[22].u = UV_MAC(0.f, 5); boxVerts[22].v = UV_MAC(1.f, 1);
		boxVerts[23].u = UV_MAC(1.f, 5); boxVerts[23].v = UV_MAC(1.f, 1);
		break;
	case LEAVES:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 4);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 3);
		}
		break;
	case SPONGE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 0);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 3);
		}
		break;
	case GLASS:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 1);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 3);
		}
		break;
	//case YELLOW_FLOWER:

	//	break;
	//case RED_ROSE:

	//	break;
	//case BROWN_MUSHROOM:

	//	break;
	//case RED_MUSHROOM:

	//	break;
	case GOLD_BLOCK:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 7); boxVerts[0].v = UV_MAC(0.f, 1);
		boxVerts[1].u = UV_MAC(1.f, 7); boxVerts[1].v = UV_MAC(0.f, 1);
		boxVerts[2].u = UV_MAC(0.f, 7); boxVerts[2].v = UV_MAC(1.f, 1);
		boxVerts[3].u = UV_MAC(1.f, 7); boxVerts[3].v = UV_MAC(1.f, 1);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 7);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}

		boxVerts[20].u = UV_MAC(0.f, 7); boxVerts[20].v = UV_MAC(0.f, 3);
		boxVerts[21].u = UV_MAC(1.f, 7); boxVerts[21].v = UV_MAC(0.f, 3);
		boxVerts[22].u = UV_MAC(0.f, 7); boxVerts[22].v = UV_MAC(1.f, 3);
		boxVerts[23].u = UV_MAC(1.f, 7); boxVerts[23].v = UV_MAC(1.f, 3);
		break;
	case IRON_BLOCK:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 6); boxVerts[0].v = UV_MAC(0.f, 1);
		boxVerts[1].u = UV_MAC(1.f, 6); boxVerts[1].v = UV_MAC(0.f, 1);
		boxVerts[2].u = UV_MAC(0.f, 6); boxVerts[2].v = UV_MAC(1.f, 1);
		boxVerts[3].u = UV_MAC(1.f, 6); boxVerts[3].v = UV_MAC(1.f, 1);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 6);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}

		boxVerts[20].u = UV_MAC(0.f, 6); boxVerts[20].v = UV_MAC(0.f, 3);
		boxVerts[21].u = UV_MAC(1.f, 6); boxVerts[21].v = UV_MAC(0.f, 3);
		boxVerts[22].u = UV_MAC(0.f, 6); boxVerts[22].v = UV_MAC(1.f, 3);
		boxVerts[23].u = UV_MAC(1.f, 6); boxVerts[23].v = UV_MAC(1.f, 3);
		break;
	case DOUBLE_STEP:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 6); boxVerts[0].v = UV_MAC(0.f, 0);
		boxVerts[1].u = UV_MAC(1.f, 6); boxVerts[1].v = UV_MAC(0.f, 0);
		boxVerts[2].u = UV_MAC(0.f, 6); boxVerts[2].v = UV_MAC(1.f, 0);
		boxVerts[3].u = UV_MAC(1.f, 6); boxVerts[3].v = UV_MAC(1.f, 0);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 5);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 0);
		}

		boxVerts[20].u = UV_MAC(0.f, 6); boxVerts[20].v = UV_MAC(0.f, 0);
		boxVerts[21].u = UV_MAC(1.f, 6); boxVerts[21].v = UV_MAC(0.f, 0);
		boxVerts[22].u = UV_MAC(0.f, 6); boxVerts[22].v = UV_MAC(1.f, 0);
		boxVerts[23].u = UV_MAC(1.f, 6); boxVerts[23].v = UV_MAC(1.f, 0);
		break;
	//case STEP:

	//	break;
	case BRICK:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 7);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 0);
		}
		break;
	case TNT:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 9); boxVerts[0].v = UV_MAC(0.f, 0);
		boxVerts[1].u = UV_MAC(1.f, 9); boxVerts[1].v = UV_MAC(0.f, 0);
		boxVerts[2].u = UV_MAC(0.f, 9); boxVerts[2].v = UV_MAC(1.f, 0);
		boxVerts[3].u = UV_MAC(1.f, 9); boxVerts[3].v = UV_MAC(1.f, 0);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 8);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 0);
		}

		boxVerts[20].u = UV_MAC(0.f, 10); boxVerts[20].v = UV_MAC(0.f, 0);
		boxVerts[21].u = UV_MAC(1.f, 10); boxVerts[21].v = UV_MAC(0.f, 0);
		boxVerts[22].u = UV_MAC(0.f, 10); boxVerts[22].v = UV_MAC(1.f, 0);
		boxVerts[23].u = UV_MAC(1.f, 10); boxVerts[23].v = UV_MAC(1.f, 0);
		break;
	case BOOKSHELF:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 4); boxVerts[0].v = UV_MAC(0.f, 0);
		boxVerts[1].u = UV_MAC(1.f, 4); boxVerts[1].v = UV_MAC(0.f, 0);
		boxVerts[2].u = UV_MAC(0.f, 4); boxVerts[2].v = UV_MAC(1.f, 0);
		boxVerts[3].u = UV_MAC(1.f, 4); boxVerts[3].v = UV_MAC(1.f, 0);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 3);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}

		boxVerts[20].u = UV_MAC(0.f, 4); boxVerts[20].v = UV_MAC(0.f, 0);
		boxVerts[21].u = UV_MAC(1.f, 4); boxVerts[21].v = UV_MAC(0.f, 0);
		boxVerts[22].u = UV_MAC(0.f, 4); boxVerts[22].v = UV_MAC(1.f, 0);
		boxVerts[23].u = UV_MAC(1.f, 4); boxVerts[23].v = UV_MAC(1.f, 0);
		break;
	case MOSSY_COBBLESTONE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 4);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}
		break;
	case OBSIDIAN:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 5);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}
		break;
	case TORCH:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].pos.x = boxVerts[iVert].pos.x * 0.125f + 0.4375f;
			boxVerts[iVert].pos.z = boxVerts[iVert].pos.z * 0.125f + 0.4375f;

			boxVerts[iVert].u = UV_LERP_PIXEL(_boxVerts[iVert].u, 7.f, 8.f);
			boxVerts[iVert].v = UV_LERP_PIXEL(_boxVerts[iVert].v, 86.f, 96.f);
		}

		// Top
		boxVerts[0].u = UV_LERP_PIXEL(0.f, 8.f, 8.f); boxVerts[0].v = UV_LERP_PIXEL(0.f, 87.f, 87.f);
		boxVerts[1].u = UV_LERP_PIXEL(1.f, 8.f, 8.f); boxVerts[1].v = UV_LERP_PIXEL(0.f, 87.f, 87.f);
		boxVerts[2].u = UV_LERP_PIXEL(0.f, 8.f, 8.f); boxVerts[2].v = UV_LERP_PIXEL(1.f, 87.f, 87.f);
		boxVerts[3].u = UV_LERP_PIXEL(1.f, 8.f, 8.f); boxVerts[3].v = UV_LERP_PIXEL(1.f, 87.f, 87.f);

		// Bottom
		boxVerts[20].u = UV_LERP_PIXEL(0.f, 8.f, 8.f); boxVerts[20].v = UV_LERP_PIXEL(0.f, 95.f, 95.f);
		boxVerts[21].u = UV_LERP_PIXEL(1.f, 8.f, 8.f); boxVerts[21].v = UV_LERP_PIXEL(0.f, 95.f, 95.f);
		boxVerts[22].u = UV_LERP_PIXEL(0.f, 8.f, 8.f); boxVerts[22].v = UV_LERP_PIXEL(1.f, 95.f, 95.f);
		boxVerts[23].u = UV_LERP_PIXEL(1.f, 8.f, 8.f); boxVerts[23].v = UV_LERP_PIXEL(1.f, 95.f, 95.f);
		break;
	//case FIRE:

	//	break;
	case MOB_SPAWNER:	
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 1);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 4);
		}
		break;
	//case WOODEN_STAIRS:

	//	break;
	case CHEST:
		//TODO: Handle double chest
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		// Top
		boxVerts[0].u = UV_MAC(0.f, 9); boxVerts[0].v = UV_MAC(0.f, 1);
		boxVerts[1].u = UV_MAC(1.f, 9); boxVerts[1].v = UV_MAC(0.f, 1);
		boxVerts[2].u = UV_MAC(0.f, 9); boxVerts[2].v = UV_MAC(1.f, 1);
		boxVerts[3].u = UV_MAC(1.f, 9); boxVerts[3].v = UV_MAC(1.f, 1);

		// Left
		boxVerts[4].u = UV_MAC(0.f, 10); boxVerts[4].v = UV_MAC(0.f, 1);
		boxVerts[5].u = UV_MAC(1.f, 10); boxVerts[5].v = UV_MAC(0.f, 1);
		boxVerts[6].u = UV_MAC(0.f, 10); boxVerts[6].v = UV_MAC(1.f, 1);
		boxVerts[7].u = UV_MAC(1.f, 10); boxVerts[7].v = UV_MAC(1.f, 1);

		// Front
		boxVerts[8].u  = UV_MAC(0.f, 11); boxVerts[8].v  = UV_MAC(0.f, 1);
		boxVerts[9].u  = UV_MAC(1.f, 11); boxVerts[9].v  = UV_MAC(0.f, 1);
		boxVerts[10].u = UV_MAC(0.f, 11); boxVerts[10].v = UV_MAC(1.f, 1);
		boxVerts[11].u = UV_MAC(1.f, 11); boxVerts[11].v = UV_MAC(1.f, 1);

		// Right
		boxVerts[12].u = UV_MAC(0.f, 10); boxVerts[12].v = UV_MAC(0.f, 1);
		boxVerts[13].u = UV_MAC(1.f, 10); boxVerts[13].v = UV_MAC(0.f, 1);
		boxVerts[14].u = UV_MAC(0.f, 10); boxVerts[14].v = UV_MAC(1.f, 1);
		boxVerts[15].u = UV_MAC(1.f, 10); boxVerts[15].v = UV_MAC(1.f, 1);

		// Back
		boxVerts[16].u = UV_MAC(0.f, 10); boxVerts[16].v = UV_MAC(0.f, 1);
		boxVerts[17].u = UV_MAC(1.f, 10); boxVerts[17].v = UV_MAC(0.f, 1);
		boxVerts[18].u = UV_MAC(0.f, 10); boxVerts[18].v = UV_MAC(1.f, 1);
		boxVerts[19].u = UV_MAC(1.f, 10); boxVerts[19].v = UV_MAC(1.f, 1);

		// Bottom
		boxVerts[20].u = UV_MAC(0.f, 9); boxVerts[20].v = UV_MAC(0.f, 3);
		boxVerts[21].u = UV_MAC(1.f, 9); boxVerts[21].v = UV_MAC(0.f, 3);
		boxVerts[22].u = UV_MAC(0.f, 9); boxVerts[22].v = UV_MAC(1.f, 3);
		boxVerts[23].u = UV_MAC(1.f, 9); boxVerts[23].v = UV_MAC(1.f, 3);
		break;
	//case REDSTONE_WIRE:

	//	break;
	case DIAMOND_ORE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 2);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 3);
		}
		break;
	case DIAMOND_BLOCK:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 8); boxVerts[0].v = UV_MAC(0.f, 1);
		boxVerts[1].u = UV_MAC(1.f, 8); boxVerts[1].v = UV_MAC(0.f, 1);
		boxVerts[2].u = UV_MAC(0.f, 8); boxVerts[2].v = UV_MAC(1.f, 1);
		boxVerts[3].u = UV_MAC(1.f, 8); boxVerts[3].v = UV_MAC(1.f, 1);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 8);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}

		boxVerts[20].u = UV_MAC(0.f, 8); boxVerts[20].v = UV_MAC(0.f, 3);
		boxVerts[21].u = UV_MAC(1.f, 8); boxVerts[21].v = UV_MAC(0.f, 3);
		boxVerts[22].u = UV_MAC(0.f, 8); boxVerts[22].v = UV_MAC(1.f, 3);
		boxVerts[23].u = UV_MAC(1.f, 8); boxVerts[23].v = UV_MAC(1.f, 3);
		break;
	case WORKBENCH:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		// Top
		boxVerts[0].u = UV_MAC(0.f, 11); boxVerts[0].v = UV_MAC(0.f, 2);
		boxVerts[1].u = UV_MAC(1.f, 11); boxVerts[1].v = UV_MAC(0.f, 2);
		boxVerts[2].u = UV_MAC(0.f, 11); boxVerts[2].v = UV_MAC(1.f, 2);
		boxVerts[3].u = UV_MAC(1.f, 11); boxVerts[3].v = UV_MAC(1.f, 2);

		// Left
		boxVerts[4].u = UV_MAC(0.f, 11); boxVerts[4].v = UV_MAC(0.f, 3);
		boxVerts[5].u = UV_MAC(1.f, 11); boxVerts[5].v = UV_MAC(0.f, 3);
		boxVerts[6].u = UV_MAC(0.f, 11); boxVerts[6].v = UV_MAC(1.f, 3);
		boxVerts[7].u = UV_MAC(1.f, 11); boxVerts[7].v = UV_MAC(1.f, 3);

		// Front
		boxVerts[8].u  = UV_MAC(0.f, 12); boxVerts[8].v  = UV_MAC(0.f, 3);
		boxVerts[9].u  = UV_MAC(1.f, 12); boxVerts[9].v  = UV_MAC(0.f, 3);
		boxVerts[10].u = UV_MAC(0.f, 12); boxVerts[10].v = UV_MAC(1.f, 3);
		boxVerts[11].u = UV_MAC(1.f, 12); boxVerts[11].v = UV_MAC(1.f, 3);

		// Right
		boxVerts[12].u = UV_MAC(0.f, 11); boxVerts[12].v = UV_MAC(0.f, 3);
		boxVerts[13].u = UV_MAC(1.f, 11); boxVerts[13].v = UV_MAC(0.f, 3);
		boxVerts[14].u = UV_MAC(0.f, 11); boxVerts[14].v = UV_MAC(1.f, 3);
		boxVerts[15].u = UV_MAC(1.f, 11); boxVerts[15].v = UV_MAC(1.f, 3);

		// Back
		boxVerts[16].u = UV_MAC(0.f, 12); boxVerts[16].v = UV_MAC(0.f, 3);
		boxVerts[17].u = UV_MAC(1.f, 12); boxVerts[17].v = UV_MAC(0.f, 3);
		boxVerts[18].u = UV_MAC(0.f, 12); boxVerts[18].v = UV_MAC(1.f, 3);
		boxVerts[19].u = UV_MAC(1.f, 12); boxVerts[19].v = UV_MAC(1.f, 3);

		// Bottom
		boxVerts[20].u = UV_MAC(0.f, 9); boxVerts[20].v = UV_MAC(0.f, 3);
		boxVerts[21].u = UV_MAC(1.f, 9); boxVerts[21].v = UV_MAC(0.f, 3);
		boxVerts[22].u = UV_MAC(0.f, 9); boxVerts[22].v = UV_MAC(1.f, 3);
		boxVerts[23].u = UV_MAC(1.f, 9); boxVerts[23].v = UV_MAC(1.f, 3);
		break;
	//case CROPS:
	//	break;
	//case SOIL:
	//	break;
	case FURNACE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		// Top
		boxVerts[0].u = UV_MAC(0.f, 1); boxVerts[0].v = UV_MAC(0.f, 0);
		boxVerts[1].u = UV_MAC(1.f, 1); boxVerts[1].v = UV_MAC(0.f, 0);
		boxVerts[2].u = UV_MAC(0.f, 1); boxVerts[2].v = UV_MAC(1.f, 0);
		boxVerts[3].u = UV_MAC(1.f, 1); boxVerts[3].v = UV_MAC(1.f, 0);

		// Left
		boxVerts[4].u = UV_MAC(0.f, 13); boxVerts[4].v = UV_MAC(0.f, 2);
		boxVerts[5].u = UV_MAC(1.f, 13); boxVerts[5].v = UV_MAC(0.f, 2);
		boxVerts[6].u = UV_MAC(0.f, 13); boxVerts[6].v = UV_MAC(1.f, 2);
		boxVerts[7].u = UV_MAC(1.f, 13); boxVerts[7].v = UV_MAC(1.f, 2);

		// Front
		boxVerts[8].u  = UV_MAC(0.f, 12); boxVerts[8].v  = UV_MAC(0.f, 2);
		boxVerts[9].u  = UV_MAC(1.f, 12); boxVerts[9].v  = UV_MAC(0.f, 2);
		boxVerts[10].u = UV_MAC(0.f, 12); boxVerts[10].v = UV_MAC(1.f, 2);
		boxVerts[11].u = UV_MAC(1.f, 12); boxVerts[11].v = UV_MAC(1.f, 2);

		// Right
		boxVerts[12].u = UV_MAC(0.f, 13); boxVerts[12].v = UV_MAC(0.f, 2);
		boxVerts[13].u = UV_MAC(1.f, 13); boxVerts[13].v = UV_MAC(0.f, 2);
		boxVerts[14].u = UV_MAC(0.f, 13); boxVerts[14].v = UV_MAC(1.f, 2);
		boxVerts[15].u = UV_MAC(1.f, 13); boxVerts[15].v = UV_MAC(1.f, 2);

		// Back
		boxVerts[16].u = UV_MAC(0.f, 13); boxVerts[16].v = UV_MAC(0.f, 2);
		boxVerts[17].u = UV_MAC(1.f, 13); boxVerts[17].v = UV_MAC(0.f, 2);
		boxVerts[18].u = UV_MAC(0.f, 13); boxVerts[18].v = UV_MAC(1.f, 2);
		boxVerts[19].u = UV_MAC(1.f, 13); boxVerts[19].v = UV_MAC(1.f, 2);

		// Bottom
		boxVerts[20].u = UV_MAC(0.f, 1); boxVerts[20].v = UV_MAC(0.f, 0);
		boxVerts[21].u = UV_MAC(1.f, 1); boxVerts[21].v = UV_MAC(0.f, 0);
		boxVerts[22].u = UV_MAC(0.f, 1); boxVerts[22].v = UV_MAC(1.f, 0);
		boxVerts[23].u = UV_MAC(1.f, 1); boxVerts[23].v = UV_MAC(1.f, 0);
		break;
	case BURNING_FURNACE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		// Top
		boxVerts[0].u = UV_MAC(0.f, 1); boxVerts[0].v = UV_MAC(0.f, 0);
		boxVerts[1].u = UV_MAC(1.f, 1); boxVerts[1].v = UV_MAC(0.f, 0);
		boxVerts[2].u = UV_MAC(0.f, 1); boxVerts[2].v = UV_MAC(1.f, 0);
		boxVerts[3].u = UV_MAC(1.f, 1); boxVerts[3].v = UV_MAC(1.f, 0);

		// Left
		boxVerts[4].u = UV_MAC(0.f, 13); boxVerts[4].v = UV_MAC(0.f, 2);
		boxVerts[5].u = UV_MAC(1.f, 13); boxVerts[5].v = UV_MAC(0.f, 2);
		boxVerts[6].u = UV_MAC(0.f, 13); boxVerts[6].v = UV_MAC(1.f, 2);
		boxVerts[7].u = UV_MAC(1.f, 13); boxVerts[7].v = UV_MAC(1.f, 2);

		// Front
		boxVerts[8].u  = UV_MAC(0.f, 13); boxVerts[8].v  = UV_MAC(0.f, 3);
		boxVerts[9].u  = UV_MAC(1.f, 13); boxVerts[9].v  = UV_MAC(0.f, 3);
		boxVerts[10].u = UV_MAC(0.f, 13); boxVerts[10].v = UV_MAC(1.f, 3);
		boxVerts[11].u = UV_MAC(1.f, 13); boxVerts[11].v = UV_MAC(1.f, 3);

		// Right
		boxVerts[12].u = UV_MAC(0.f, 13); boxVerts[12].v = UV_MAC(0.f, 2);
		boxVerts[13].u = UV_MAC(1.f, 13); boxVerts[13].v = UV_MAC(0.f, 2);
		boxVerts[14].u = UV_MAC(0.f, 13); boxVerts[14].v = UV_MAC(1.f, 2);
		boxVerts[15].u = UV_MAC(1.f, 13); boxVerts[15].v = UV_MAC(1.f, 2);

		// Back
		boxVerts[16].u = UV_MAC(0.f, 13); boxVerts[16].v = UV_MAC(0.f, 2);
		boxVerts[17].u = UV_MAC(1.f, 13); boxVerts[17].v = UV_MAC(0.f, 2);
		boxVerts[18].u = UV_MAC(0.f, 13); boxVerts[18].v = UV_MAC(1.f, 2);
		boxVerts[19].u = UV_MAC(1.f, 13); boxVerts[19].v = UV_MAC(1.f, 2);

		// Bottom
		boxVerts[20].u = UV_MAC(0.f, 1); boxVerts[20].v = UV_MAC(0.f, 0);
		boxVerts[21].u = UV_MAC(1.f, 1); boxVerts[21].v = UV_MAC(0.f, 0);
		boxVerts[22].u = UV_MAC(0.f, 1); boxVerts[22].v = UV_MAC(1.f, 0);
		boxVerts[23].u = UV_MAC(1.f, 1); boxVerts[23].v = UV_MAC(1.f, 0);
		break;
	//case SIGN_POST:
	//	break;
	//case WOODEN_DOOR:
	//	break;
	//case LADDER:
	//	break;
	//case MINECART_TRACKS:
	//	break;
	//case COBBLESTONE_STAIRS:
	//	break;
	//case WALL_SIGN:
	//	break;
	//case LEVER:
	//	break;
	//case STONE_PRESSURE_PLATE:
	//	break;
	//case IRON_DOOR:
	//	break;
	//case WOODEN_PRESSURE_PLATE:
	//	break;
	//case REDSTONE_ORE:
	//	break;
	//case GLOWING_REDSTONE_ORE:
	//	break;
	//case REDSTONE_TORCH_OFF:
	//	break;
	//case REDSTONE_TORCH_ON:
	//	break;
	//case STONE_BUTTON:
	//	break;
	//case SNOW:
	//	break;
	//case ICE:
	//	break;
	case SNOW_BLOCK:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 2);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 4);
		}
		break;
	case CACTUS:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 5); boxVerts[0].v = UV_MAC(0.f, 4);
		boxVerts[1].u = UV_MAC(1.f, 5); boxVerts[1].v = UV_MAC(0.f, 4);
		boxVerts[2].u = UV_MAC(0.f, 5); boxVerts[2].v = UV_MAC(1.f, 4);
		boxVerts[3].u = UV_MAC(1.f, 5); boxVerts[3].v = UV_MAC(1.f, 4);

		for (int iVert = 4; iVert < 20; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 6);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 4);
		}

		boxVerts[20].u = UV_MAC(0.f, 7); boxVerts[20].v = UV_MAC(0.f, 4);
		boxVerts[21].u = UV_MAC(1.f, 7); boxVerts[21].v = UV_MAC(0.f, 4);
		boxVerts[22].u = UV_MAC(0.f, 7); boxVerts[22].v = UV_MAC(1.f, 4);
		boxVerts[23].u = UV_MAC(1.f, 7); boxVerts[23].v = UV_MAC(1.f, 4);
		break;
	case CLAY:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 8);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 4);
		}
		break;
	//case REED:
	//	break;
	case JUKEBOX:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		boxVerts[0].u = UV_MAC(0.f, 11); boxVerts[0].v = UV_MAC(0.f, 4);
		boxVerts[1].u = UV_MAC(1.f, 11); boxVerts[1].v = UV_MAC(0.f, 4);
		boxVerts[2].u = UV_MAC(0.f, 11); boxVerts[2].v = UV_MAC(1.f, 4);
		boxVerts[3].u = UV_MAC(1.f, 11); boxVerts[3].v = UV_MAC(1.f, 4);

		for (int iVert = 4; iVert < 24; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 10);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 4);
		}
		break;
	//case FENCE:
	//	break;
	case PUMPKIN:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		// Top
		boxVerts[0].u = UV_MAC(0.f, 6); boxVerts[0].v = UV_MAC(0.f, 6);
		boxVerts[1].u = UV_MAC(1.f, 6); boxVerts[1].v = UV_MAC(0.f, 6);
		boxVerts[2].u = UV_MAC(0.f, 6); boxVerts[2].v = UV_MAC(1.f, 6);
		boxVerts[3].u = UV_MAC(1.f, 6); boxVerts[3].v = UV_MAC(1.f, 6);

		// Left
		boxVerts[4].u = UV_MAC(0.f, 6); boxVerts[4].v = UV_MAC(0.f, 7);
		boxVerts[5].u = UV_MAC(1.f, 6); boxVerts[5].v = UV_MAC(0.f, 7);
		boxVerts[6].u = UV_MAC(0.f, 6); boxVerts[6].v = UV_MAC(1.f, 7);
		boxVerts[7].u = UV_MAC(1.f, 6); boxVerts[7].v = UV_MAC(1.f, 7);

		// Front
		boxVerts[8].u  = UV_MAC(0.f, 7); boxVerts[8].v  = UV_MAC(0.f, 7);
		boxVerts[9].u  = UV_MAC(1.f, 7); boxVerts[9].v  = UV_MAC(0.f, 7);
		boxVerts[10].u = UV_MAC(0.f, 7); boxVerts[10].v = UV_MAC(1.f, 7);
		boxVerts[11].u = UV_MAC(1.f, 7); boxVerts[11].v = UV_MAC(1.f, 7);

		// Right
		boxVerts[12].u = UV_MAC(0.f, 6); boxVerts[12].v = UV_MAC(0.f, 6);
		boxVerts[13].u = UV_MAC(1.f, 6); boxVerts[13].v = UV_MAC(0.f, 6);
		boxVerts[14].u = UV_MAC(0.f, 6); boxVerts[14].v = UV_MAC(1.f, 6);
		boxVerts[15].u = UV_MAC(1.f, 6); boxVerts[15].v = UV_MAC(1.f, 6);

		// Back
		boxVerts[16].u = UV_MAC(0.f, 6); boxVerts[16].v = UV_MAC(0.f, 6);
		boxVerts[17].u = UV_MAC(1.f, 6); boxVerts[17].v = UV_MAC(0.f, 6);
		boxVerts[18].u = UV_MAC(0.f, 6); boxVerts[18].v = UV_MAC(1.f, 6);
		boxVerts[19].u = UV_MAC(1.f, 6); boxVerts[19].v = UV_MAC(1.f, 6);

		// Bottom
		boxVerts[20].u = UV_MAC(0.f, 6); boxVerts[20].v = UV_MAC(0.f, 6);
		boxVerts[21].u = UV_MAC(1.f, 6); boxVerts[21].v = UV_MAC(0.f, 6);
		boxVerts[22].u = UV_MAC(0.f, 6); boxVerts[22].v = UV_MAC(1.f, 6);
		boxVerts[23].u = UV_MAC(1.f, 6); boxVerts[23].v = UV_MAC(1.f, 6);
		break;
		break;
	case NETHERSTONE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 7);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 6);
		}
		break;
	case SLOW_SAND:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 8);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 6);
		}
		break;
	case LIGHTSTONE:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 9);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 6);
		}
		break;
	//case PORTAL:
	//	break;
	case JACK_O_LANTERN:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		// Top
		boxVerts[0].u = UV_MAC(0.f, 6); boxVerts[0].v = UV_MAC(0.f, 6);
		boxVerts[1].u = UV_MAC(1.f, 6); boxVerts[1].v = UV_MAC(0.f, 6);
		boxVerts[2].u = UV_MAC(0.f, 6); boxVerts[2].v = UV_MAC(1.f, 6);
		boxVerts[3].u = UV_MAC(1.f, 6); boxVerts[3].v = UV_MAC(1.f, 6);

		// Left
		boxVerts[4].u = UV_MAC(0.f, 6); boxVerts[4].v = UV_MAC(0.f, 7);
		boxVerts[5].u = UV_MAC(1.f, 6); boxVerts[5].v = UV_MAC(0.f, 7);
		boxVerts[6].u = UV_MAC(0.f, 6); boxVerts[6].v = UV_MAC(1.f, 7);
		boxVerts[7].u = UV_MAC(1.f, 6); boxVerts[7].v = UV_MAC(1.f, 7);

		// Front
		boxVerts[8].u  = UV_MAC(0.f, 8); boxVerts[8].v  = UV_MAC(0.f, 7);
		boxVerts[9].u  = UV_MAC(1.f, 8); boxVerts[9].v  = UV_MAC(0.f, 7);
		boxVerts[10].u = UV_MAC(0.f, 8); boxVerts[10].v = UV_MAC(1.f, 7);
		boxVerts[11].u = UV_MAC(1.f, 8); boxVerts[11].v = UV_MAC(1.f, 7);

		// Right
		boxVerts[12].u = UV_MAC(0.f, 6); boxVerts[12].v = UV_MAC(0.f, 6);
		boxVerts[13].u = UV_MAC(1.f, 6); boxVerts[13].v = UV_MAC(0.f, 6);
		boxVerts[14].u = UV_MAC(0.f, 6); boxVerts[14].v = UV_MAC(1.f, 6);
		boxVerts[15].u = UV_MAC(1.f, 6); boxVerts[15].v = UV_MAC(1.f, 6);

		// Back
		boxVerts[16].u = UV_MAC(0.f, 6); boxVerts[16].v = UV_MAC(0.f, 6);
		boxVerts[17].u = UV_MAC(1.f, 6); boxVerts[17].v = UV_MAC(0.f, 6);
		boxVerts[18].u = UV_MAC(0.f, 6); boxVerts[18].v = UV_MAC(1.f, 6);
		boxVerts[19].u = UV_MAC(1.f, 6); boxVerts[19].v = UV_MAC(1.f, 6);

		// Bottom
		boxVerts[20].u = UV_MAC(0.f, 6); boxVerts[20].v = UV_MAC(0.f, 6);
		boxVerts[21].u = UV_MAC(1.f, 6); boxVerts[21].v = UV_MAC(0.f, 6);
		boxVerts[22].u = UV_MAC(0.f, 6); boxVerts[22].v = UV_MAC(1.f, 6);
		boxVerts[23].u = UV_MAC(1.f, 6); boxVerts[23].v = UV_MAC(1.f, 6);
		break;
	default:
		prims[_type] = 12;
		verts[_type] = 24;

		boxVerts = new BOX_VERTEX_INSTANCE[verts[_type]];
		memcpy_s((void *)boxVerts, boxSize, (void *)_boxVerts, boxSize);

		for (int iVert = 0; iVert < verts[_type]; ++iVert)
		{
			boxVerts[iVert].u = UV_MAC(_boxVerts[iVert].u, 15);
			boxVerts[iVert].v = UV_MAC(_boxVerts[iVert].v, 2);
		}
		break;
	}


	g_D3D.pDev->CreateVertexBuffer(BUFFER_SIZE * boxSize, 0, 0, D3DPOOL_DEFAULT, &vertBuffers[_type], NULL);
	
	UBYTE *pData;
	vertBuffers[_type]->Lock(0, BUFFER_SIZE * boxSize, (void **)&pData, 0);
	{
		BOX_VERTEX_INSTANCE *bData = (BOX_VERTEX_INSTANCE *)pData;
		ZeroMemory(pData, boxSize * BUFFER_SIZE);
		memcpy_s((void *)pData, boxSize, (void *)boxVerts, boxSize);

		int bufferSize = 1;
		do
		{
			memcpy_s((void *)(pData + bufferSize * boxSize), boxSize * bufferSize, (void *)pData, boxSize * bufferSize);
			bufferSize <<= 1;
		}
		while (bufferSize < BUFFER_SIZE);

		for (int iBlock = 0; iBlock < BUFFER_SIZE * verts[_type]; ++iBlock)
			bData[iBlock].i = (float)(iBlock / verts[_type]);
	}
	vertBuffers[_type]->Unlock();

	delete[] boxVerts;
}
